package user

import (
	"context"

	"mall/common/globalkey"
	"mall/common/modelx"
	"mall/service/backend/common/utils/pointy"
	"mall/service/backend/model"
	"mall/service/backend/rpc/internal/svc"
	"mall/service/backend/rpc/internal/utils/errorhandler"
	"mall/service/backend/rpc/types/backend"

	"github.com/zeromicro/go-zero/core/logx"
)

type GetUserByUsernameLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewGetUserByUsernameLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetUserByUsernameLogic {
	return &GetUserByUsernameLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

// group: user
func (l *GetUserByUsernameLogic) GetUserByUsername(in *backend.UsernameReq) (*backend.UserInfo, error) {
	res, err := l.svcCtx.SysUser.FindOneByUsername(l.ctx, in.Username)
	if err != nil {
		return nil, errorhandler.DefaultRepositoryError(l.Logger, err, in)
	}

	var roleIds []uint64
	var roleCodes []string
	if in.WithRoles != nil && *in.WithRoles > 0 {
		preFilterMap := make(map[string]map[string][]any)
		preFilterMap[model.SysUserRoleRelationshipColumns.UserID] = map[string][]any{
			"equalTo": []any{res.ID},
		}
		rel, _, err := l.svcCtx.SysUser.GetRelRoleList(l.ctx, model.M{}, -1, preFilterMap)
		if err != nil {
			return nil, errorhandler.DefaultRepositoryError(l.Logger, err, in)
		}

		if len(rel) > 0 {
			var rids []any
			for _, v := range rel {
				rids = append(rids, v.RoleID)
			}

			filterMap := make(map[string]map[string][]any)
			filterMap[model.SysRoleColumns.ID] = map[string][]any{
				"in": rids,
			}
			filterMap[model.SysRoleColumns.Status] = map[string][]any{
				"equalTo": []any{globalkey.StatusEnabled},
			}
			roles, _, err := l.svcCtx.SysRole.GetList(l.ctx, model.M{
				"select": model.SysRoleColumns.ID + "," + model.SysRoleColumns.Code,
			}, -1, filterMap)
			if err != nil {
				return nil, errorhandler.DefaultRepositoryError(l.Logger, err, in)
			}

			if len(roles) > 0 {
				for _, v := range roles {
					roleIds = append(roleIds, v.ID)
					roleCodes = append(roleCodes, v.Code)
				}
			}
		}
	}

	var positionIds []uint64
	if in.WithPositions != nil && *in.WithPositions > 0 {
		preFilterMap := make(map[string]map[string][]any)
		preFilterMap[model.SysUserPositionRelationshipColumns.UserID] = map[string][]any{
			"equalTo": []any{res.ID},
		}
		rel, _, err := l.svcCtx.SysUser.GetRelPositionList(l.ctx, model.M{}, -1, preFilterMap)
		if err != nil {
			return nil, errorhandler.DefaultRepositoryError(l.Logger, err, in)
		}

		if len(rel) > 0 {
			var pids []any
			for _, v := range rel {
				pids = append(pids, v.PositionID)
			}

			filterMap := make(map[string]map[string][]any)
			filterMap[model.SysPositionColumns.ID] = map[string][]any{
				"in": pids,
			}
			filterMap[model.SysPositionColumns.Status] = map[string][]any{
				"equalTo": []any{globalkey.StatusEnabled},
			}
			positions, _, err := l.svcCtx.SysPosition.GetList(l.ctx, model.M{
				"select": ",",
			}, -1, filterMap)
			if err != nil {
				return nil, errorhandler.DefaultRepositoryError(l.Logger, err, in)
			}

			if len(positions) > 0 {
				for _, v := range positions {
					positionIds = append(positionIds, v.ID)
				}
			}
		}
	}

	return &backend.UserInfo{
		Id:           pointy.GetPointer(res.ID),
		Username:     &res.Username,
		Nickname:     &res.Nickname,
		Description:  &res.Description,
		HomePath:     &res.HomePath,
		Mobile:       &res.Mobile,
		Email:        &res.Email,
		Avatar:       &res.Avatar,
		DepartmentId: &res.DepartmentID,
		Status:       pointy.GetPointer(uint32(res.Status)),
		RoleIds:      roleIds,
		RoleCodes:    roleCodes,
		PositionIds:  positionIds,
		CreatedAt:    pointy.GetPointer(modelx.FormatTime(res.CreatedAt, "")),
		UpdatedAt:    pointy.GetPointer(modelx.FormatTime(res.UpdatedAt, "")),
		DeletedAt:    pointy.GetPointer(modelx.FormatNullDotTime(res.DeletedAt, "")),
	}, nil
}
